package hkust.ee.fyp;

import hkust.ee.fyp.tool.FacebookPhoto;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Vector;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;

import com.facebook.android.Facebook;

public class FacebookActivity extends Activity {

	public static final int MENU_REFRESH = Menu.FIRST;
	public static final String rootDir = "/sdcard/.temp/";
	
	private boolean isFolderView = true;
	private Vector<FacebookDirectory> imageDirectory = null;
	private FacebookDirectory directory = null;
	private ImageAdapter imageAdapter=null; 
	private ProgressDialog progressDialog = null;
	private Queue<Integer> processImage=null;
	
//	handler
	private Handler dataHandler,uiHandler;
	public static final int HANDLER_PHOTO_DOWNLOAD_START = 0;
	public static final int HANDLER_PHOTO_THUMB = 1;
	public static final int HANDLER_PHOTO_DOWNLOAD_FINSIH = 2;
	public static final int HANDLER_ALBUM_DOWNLOAD_START = 3;
	public static final int HANDLER_ALBUM_DOWNLOAD_FINISH = 4;
	public static final int HANDLER_PHOTO_FROCE = 5;	

	
	public static final int HANDLER_MODE_FOLDER = 10;
	public static final int HANDLER_MODE_IMAGE = 11;
	public static final int HANDLER_MODE_PROGRESS_SHOW = 12;
	public static final int HANDLER_MODE_PROGRESS_DISMISS = 13;
	public static final int HANDLER_UPDATE_IMAGE = 14;
	
	//facebook
	private static final String APP_ID = "207571395929037";
	private Facebook facebook = new Facebook(APP_ID);
	
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		menu.add(0, MENU_REFRESH, 0, "refresh");
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		super.onOptionsItemSelected(item);
		switch (item.getItemId()) {
			case MENU_REFRESH:
				dataHandler.sendEmptyMessage(HANDLER_ALBUM_DOWNLOAD_START);		
				break;			
		}
		return true;
	}
	
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		SharedPreferences settings = getSharedPreferences(PhotoFrame.TAG, 0);
		facebook.setAccessToken(settings.getString("facebookToken", null));

		if(!facebook.isSessionValid()){
			finish();
		}
				
		uiHandler = new Handler() {
			public void handleMessage(Message msg) {				
				switch (msg.what) {							
					case HANDLER_MODE_FOLDER:
						toFolderPage();
						break;			
					case HANDLER_MODE_IMAGE:
						FacebookDirectory dir = (FacebookDirectory) msg.obj;
						toImagePage(dir);
						break;
					case HANDLER_MODE_PROGRESS_SHOW:
						if(progressDialog !=null && progressDialog.isShowing()){

						}else{
							progressDialog = ProgressDialog.show(FacebookActivity.this, "", "Loading..", false, false);;
						}
						break;
					case HANDLER_MODE_PROGRESS_DISMISS:
						if(progressDialog!=null && progressDialog.isShowing()){
							progressDialog.dismiss();
						}
						break;
					case HANDLER_UPDATE_IMAGE:
						Log.d("uiHandler", "update image view");
						if(imageAdapter != null){
							imageAdapter.notifyDataSetChanged();
						}
				}
			}
		};
		new Thread(){
			public void run(){
				Log.d("looper", "run start");
				Looper.prepare();
				dataHandler = new Handler() {
					public void handleMessage(Message msg) {				
						switch (msg.what) {							
							case HANDLER_PHOTO_DOWNLOAD_START:{
								try {
									Log.d("dataHanlder", "Received photo start");
									Integer position = processImage.poll();
									if(position==null){
										break;
									}
									FacebookPhoto single = directory.getFacebookPhoto().get(position);
									if(!single.isFinsih()){
										single.start();
										try {
											single.join();
											Log.d("dataHanlder", "Received photo start");
										} catch (InterruptedException e) {
											e.printStackTrace();
										} finally{
											Message message = Message.obtain();
											message.what = HANDLER_PHOTO_DOWNLOAD_FINSIH;
											message.arg1 = position;
											Log.d("dataHanlder", "send photo finish");
											dataHandler.sendMessageAtFrontOfQueue(message);
										}
									}
								} catch (Exception e) {
									e.printStackTrace();
								}
								break;
							}
							case HANDLER_PHOTO_THUMB:{
								Integer position = processImage.poll();
								if(position != null){
									File file = new File(directory.getImageList().get(position).getPath());
									if(!file.exists()){
										processImage.add(position);
										Message message = Message.obtain();
										message.what = HANDLER_PHOTO_DOWNLOAD_START;										
										dataHandler.sendMessage(message);
										break;
									}else{
										msg.arg1 = position;
									}
								}else{
									break;
								}
							}
							case HANDLER_PHOTO_DOWNLOAD_FINSIH:{
								Log.d("dataHanlder", "Received photo finish");
								Bitmap destBm=null;
								File f = null;
								int position = msg.arg1;
								try {									
									String filePath = directory.getImageList().get(position).getPath();
									String thumbDirPath = rootDir + "/" +  directory.getAlbumID() + "/.thumbnails/";	
									String thumbPath = directory.getThumbnaiList().get(position).getPath();	
									f =  new File(thumbDirPath);
									f.mkdir();									
									f =  new File(thumbPath);
									if(!f.exists()){
										f.createNewFile();
										
										int maxLength = 200;	  
								        BitmapFactory.Options opts = new BitmapFactory.Options();  	
								        opts.inJustDecodeBounds = true;
								        BitmapFactory.decodeFile(filePath, opts);  
								  
								        int srcWidth = opts.outWidth;  		  
								        int srcHeight = opts.outHeight;  
								  
								        int destWidth = 0;  		  
								        int destHeight = 0;  
								  
								        double ratio = 0.0;
								  
								       if(srcWidth >srcHeight) {
									        ratio = srcWidth / maxLength;  
									        destWidth = maxLength;  
									        destHeight = (int) (srcHeight / ratio);
								        }else {  
								            ratio = srcHeight / maxLength;
								            destHeight = maxLength;  
								            destWidth = (int) (srcWidth / ratio);
								        }  
								  
								        BitmapFactory.Options newOpts = new BitmapFactory.Options();  
								        newOpts.inSampleSize = (int) ratio + 1;  
								        newOpts.inJustDecodeBounds = false;  
								        newOpts.outHeight = destHeight;
								        newOpts.outWidth = destWidth;  
										
								        destBm = BitmapFactory.decodeFile(filePath, newOpts); 	
										FileOutputStream out = new FileOutputStream(thumbPath);
										destBm.compress(Bitmap.CompressFormat.PNG, 100, out);
										out.flush();
										out.close();
										
									}
								} catch (Exception e) {
//									e.printStackTrace();
									if(f!=null){
										f.delete();
									}
								} finally{
									if (null != destBm && !destBm.isRecycled()) {
										destBm.recycle();
									}
									Log.d("dataHanlder", "refresh ui");
									Message message = Message.obtain();
									message.what = HANDLER_UPDATE_IMAGE;
									message.arg1 = position;
									uiHandler.sendMessage(message);
									
									if(processImage !=null && !processImage.isEmpty()){								
										dataHandler.sendEmptyMessage(HANDLER_PHOTO_DOWNLOAD_START);
									}
								}
								break;
							}
							case HANDLER_ALBUM_DOWNLOAD_START:{
								uiHandler.sendEmptyMessage(HANDLER_MODE_PROGRESS_SHOW);							
								try {
									imageDirectory = new Vector<FacebookDirectory>();
									String response = facebook.request("me/albums");
									Log.d("me/albums", response);
									try {
										JSONObject json = new JSONObject(response);
										JSONArray d = json.getJSONArray("data");
										int l = (d != null ? d.length() : 0);

										for (int i = 0; i < l; i++) {
											JSONObject o = d.getJSONObject(i);
											FacebookDirectory directory = 
												new FacebookDirectory(o.getString("name"),o.getString("id"));
											imageDirectory.add(directory);
											File file = new File(rootDir+"/"+o.getString("id"));
											file.mkdir();
										}
										
										int size = imageDirectory.size();										
										for (int j = 0; j < size; j++) {
											FacebookDirectory directory = imageDirectory.get(j);
											
											response = facebook.request(directory.getAlbumID() + "/photos");
											Log.d("me/albums", response);
											json = new JSONObject(response);
											d = json.getJSONArray("data");
											l = (d != null ? d.length(): 0);

											for (int i = 0; i < l; i++) {
												JSONObject o = d.getJSONObject(i);
												directory.addImage(o.getString("id"), o.getString("source"), o.getString("picture"));
											}						
										}
										
										Log.d("me/albums", "ALL");
									} catch (JSONException e) {
										Log.w("Facebook-Example", "JSON Error in response");
									}
									
								} catch (MalformedURLException e1) {
									e1.printStackTrace();
								} catch (IOException e1) {
									e1.printStackTrace();
								}
								
								for(FacebookDirectory d : imageDirectory){
									if(d.getFacebookPhoto().size()==0){
										continue;
									}
									FacebookPhoto single = d.getFacebookPhoto().get(0);
									if(!single.isFinsih()){
										single.start();
										try {
											single.join();
										} catch (InterruptedException e) {
											e.printStackTrace();
										} finally{
											
										}
									}		
									
									Bitmap destBm=null;
									File f = null;
									try {									
										String filePath = d.getImageList().get(0).getPath();
										String thumbDirPath = rootDir + "/" +  d.getAlbumID() + "/.thumbnails/";	
										String thumbPath = d.getThumbnaiList().get(0).getPath();	
										f =  new File(thumbDirPath);
										f.mkdir();									
										f =  new File(thumbPath);
										if(!f.exists()){
											f.createNewFile();
											
											int maxLength = 200;	  
									        BitmapFactory.Options opts = new BitmapFactory.Options();  	
									        opts.inJustDecodeBounds = true;
									        BitmapFactory.decodeFile(filePath, opts);  
									  
									        int srcWidth = opts.outWidth;  		  
									        int srcHeight = opts.outHeight;  
									  
									        int destWidth = 0;  		  
									        int destHeight = 0;  
									  
									        double ratio = 0.0;
									  
									       if(srcWidth >srcHeight) {
										        ratio = srcWidth / maxLength;  
										        destWidth = maxLength;  
										        destHeight = (int) (srcHeight / ratio);
									        }else {  
									            ratio = srcHeight / maxLength;
									            destHeight = maxLength;  
									            destWidth = (int) (srcWidth / ratio);
									        }  
									  
									        BitmapFactory.Options newOpts = new BitmapFactory.Options();  
									        newOpts.inSampleSize = (int) ratio + 1;  
									        newOpts.inJustDecodeBounds = false;  
									        newOpts.outHeight = destHeight;
									        newOpts.outWidth = destWidth;  
											
									        destBm = BitmapFactory.decodeFile(filePath, newOpts); 	
											FileOutputStream out = new FileOutputStream(thumbPath);
											destBm.compress(Bitmap.CompressFormat.PNG, 100, out);
											out.flush();
											out.close();					
										}
									} catch (Exception e) {
										if(f!=null){
											f.delete();
										}
									} finally{
										if (null != destBm && !destBm.isRecycled()) {
											destBm.recycle();
										}				
									}
								}
																
//								break;
							}
							case HANDLER_ALBUM_DOWNLOAD_FINISH:{
								uiHandler.sendEmptyMessage(HANDLER_MODE_PROGRESS_DISMISS);
								if(isFolderView){
									uiHandler.sendEmptyMessage(HANDLER_MODE_FOLDER);
								}else{
									FacebookDirectory dir=null;
									for(FacebookDirectory d: imageDirectory){
										if(d.getAlbumID().compareTo(directory.getAlbumID())==0){
											dir = d;
											break;
										}
									}
									if(dir!=null){
										Message m = Message.obtain();
										m.what = HANDLER_MODE_IMAGE;
										m.obj = dir;
										uiHandler.sendMessage(m);
									}else{
										uiHandler.sendEmptyMessage(HANDLER_MODE_FOLDER);
									}
								}
								break;
							}
							case HANDLER_PHOTO_FROCE:{
								uiHandler.sendEmptyMessage(HANDLER_MODE_PROGRESS_SHOW);
								Integer position = msg.arg1;
								processImage.remove(position);								
								FacebookPhoto single = directory.getFacebookPhoto().get(position);
								try {
									if(!single.isFinsih()){
										single.start();
										single.join();
										uiHandler.sendEmptyMessage(HANDLER_MODE_PROGRESS_DISMISS);		
										Message message = Message.obtain();
										message.what = HANDLER_PHOTO_DOWNLOAD_FINSIH;
										message.arg1 = position;
										Log.d("dataHanlder", "send photo finish");
										dataHandler.sendMessageAtFrontOfQueue(message);
										Thread.sleep(500);
									}
									Log.d("dataHanlder", "Received photo start");
								} catch (InterruptedException e) {
									e.printStackTrace();
								} finally{
									openImage(directory.getImageList().get(position));
								}
								break;
							}		 
						}
					}
				};
				Looper.loop();
				Log.d("looper", "run end");
			}
		}.start();

		File f = new File(rootDir);
		f.mkdir();
		
		while(dataHandler==null){
			Log.d("onCreate", "dataHandler null");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		dataHandler.sendEmptyMessage(HANDLER_ALBUM_DOWNLOAD_START);	
	}	
	
	protected void onResume() {
		super.onResume();
	}
	

	
	private void toFolderPage() {
		if(imageDirectory==null){
			dataHandler.sendEmptyMessage(HANDLER_ALBUM_DOWNLOAD_START);
			return;
		}
		
		isFolderView = true;
		dataHandler.removeMessages(HANDLER_ALBUM_DOWNLOAD_START);
		dataHandler.removeMessages(HANDLER_ALBUM_DOWNLOAD_FINISH);
		directory = null;
		imageAdapter = null;
		
		
		View view = getLayoutInflater().inflate(R.layout.gallery_gridlayout_folder,null);
		GridView gridview = (GridView) view.findViewById(R.id.folder_gridView);
		FolderAdapter adapter = new FolderAdapter(imageDirectory);
		gridview.setAdapter(adapter);
		gridview.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView<?> parent, View v,int position, long id) {
					toImagePage(imageDirectory.get(position));
			}
		});
		
		setContentView(view);
	}


	private void toImagePage(final FacebookDirectory dir) {
		isFolderView = false;
		directory = dir;
		
		processImage = new LinkedList<Integer>();
		for(int i=0;i<dir.getImageList().size();i++){
			File file = new File(dir.getImageList().get(i).getPath());
			if(!file.exists()){
				processImage.add(i);
			}
		}
		dataHandler.sendEmptyMessage(HANDLER_PHOTO_DOWNLOAD_START);
		
		View view = getLayoutInflater().inflate(R.layout.gallery_gridlayout_image,null);
		GridView gridview = (GridView) view.findViewById(R.id.image_gridView);
		
		imageAdapter = new ImageAdapter( dir.getThumbnaiList());
		gridview.setAdapter(imageAdapter);
		gridview.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView<?> parent, View v,int position, long id) {
				try {
					File file = new File(dir.getImageList().get(position).getPath());
					if(file.exists()){
						openImage(dir.getImageList().get(position));
					}else{
						Message msg = Message.obtain();
						msg.what = HANDLER_PHOTO_FROCE;
						msg.arg1 = position;
						dataHandler.sendMessageAtFrontOfQueue(msg);
					}
				} catch (Exception e) {
//					e.printStackTrace();
				}
		        
				
			}
		});
		
		setContentView(view);
	}

	private void openImage(Uri path) {
		Intent i = new Intent(this, PhotoViewer.class);
		i.setDataAndType(Uri.parse("file://" + path), "image/*");
		startActivity(i);
	}


	
	public boolean onKeyDown(int keyCode, KeyEvent msg) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			if (!isFolderView) {
				toFolderPage();
				return true;
			}
		}

		return super.onKeyDown(keyCode, msg);
	}

	

	public class ImageAdapter extends BaseAdapter {
		private List<Uri> list = null;
		
		public ImageAdapter( List<Uri> list) {
			this.list = list;
		}

		public int getCount() {
			return list.size();
		}

		public View getItem(int position) {
			return null;
		}

		public long getItemId(int position) {
			return 0;
		}

		public View getView(int position, View convertView, ViewGroup parent) {
			View view;
			if (convertView == null) { 
				view = FacebookActivity.this.getLayoutInflater().inflate(R.layout.image_adapter, null);
			} else {
				view = convertView;
			}
			try {
				File file = new File(list.get(position).getPath());
				ImageView imageView = 
					((ImageView) view.findViewById(R.id.image_adapter_imageView));
				if(file.exists()){					
					imageView.setImageURI(list.get(position));
				}else{
					imageView.setImageResource(R.drawable.loading);
				}
			}catch (Exception e) {
				e.printStackTrace();				
			}
			
			return view;
		}

	}
	
	public class FolderAdapter extends BaseAdapter {
		private List<FacebookDirectory> list = null;

		public FolderAdapter(List<FacebookDirectory> list) {
			this.list = list;			
		}

		public int getCount() {
			return list.size();
		}

		public View getItem(int position) {
			return null;
		}

		public long getItemId(int position) {
			return 0;
		}

		
		public View getView(int position, View convertView, ViewGroup parent) {
			View view;
			if (convertView == null) { 
				view = FacebookActivity.this.getLayoutInflater().inflate(R.layout.folder_adapter, null);				
			} else {
				view = convertView;
			}
			try {
				File file = new File(list.get(position).getThumbnaiList().get(0).getPath());
				ImageView imageView = 
					((ImageView) view.findViewById(R.id.folder_adapter_imageView));
				if(file.exists()){
					imageView.setImageURI(list.get(position).getThumbnaiList().get(0));
				}else{
					imageView.setImageResource(R.drawable.loading);
				}
			} catch (Exception e) {
				e.printStackTrace();				
			}
			((TextView) view.findViewById(R.id.folder_adapter_textView))
				.setText(list.get(position).getAlbumName());
						
			return view;
		}
	}
	
	public class FacebookDirectory{
		Vector<FacebookPhoto> photoList;
		Vector<Uri> imageList;
		Vector<Uri> thumbnailList;
		String albumName=null;		
		String aid=null;
		static final String prefix = "/.thumbnails/";
		public FacebookDirectory(String albumName,String aid){
			this.albumName=albumName;
			imageList = new Vector<Uri>();
			thumbnailList = new Vector<Uri>();
			photoList = new Vector<FacebookPhoto>();
			this.aid = aid;
		}
		
		public void addImage(String pid,String srcUrl,String thumbUrl){
//			String fileName = srcUrl.substring(srcUrl.lastIndexOf("/")+1);	
//			String file = fileName.substring(0, fileName.lastIndexOf("."));
			String fileName = pid + ".jpg";
			String file = pid;
//			Log.d("adding", fileName);
//			Log.d("adding", file);
			imageList.add(Uri.parse(rootDir+ "/" +aid + "/" + fileName));
			thumbnailList.add(Uri.parse(rootDir+ "/" +aid + prefix + file));
			FacebookPhoto fb = 
				new FacebookPhoto(rootDir+ "/" +aid + "/",pid,srcUrl,null);
			photoList.add(fb);
		}
		
		public List<FacebookPhoto> getFacebookPhoto(){
			return photoList;
		}
		
		public List<Uri> getImageList() {
			return imageList;
		}
		
		public List<Uri> getThumbnaiList() {
			return thumbnailList;
		}
		
		public String getAlbumName(){
			return albumName;
		}
		
		public String getAlbumID(){
			return aid;
		}
	}
	
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
	    facebook.authorizeCallback(requestCode, resultCode, data);
		super.onActivityResult(requestCode, resultCode, data);
	}
	
}